home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2000 #5 / Amiga Plus CD - 2000 - No. 5.iso / Tools / Musik / Misc / Amster / Source / napster.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-01-01  |  14.9 KB  |  787 lines

  1. /*
  2. ** Napster Protocol
  3. */
  4.  
  5. #include "include/config.h"
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10.  
  11. #include <proto/exec.h>
  12. #include <proto/socket.h>
  13. #include <netdb.h>
  14. #include <sys/time.h>
  15. #include <sys/socket.h>
  16. #include <sys/ioctl.h>
  17. #include <netinet/tcp.h>
  18. #include <bsdsocket/socketbasetags.h>
  19. #include <error.h>
  20.  
  21. #include "include/gui.h"
  22. #include "include/channellist.h"
  23. #include "include/hotlist.h"
  24. #include "include/msg.h"
  25. #include "include/napster.h"
  26. #include "include/navigator.h"
  27. #include "include/protos.h"
  28. #include "include/prefs.h"
  29. #include "include/share.h"
  30. #include "include/transfer.h"
  31. #include "include/download.h"
  32. #include "include/upload.h"
  33. #include "amster_Cat.h"
  34.  
  35. #define NAP_SWAPIP(x) ( ((x&0xFF)<<24) | ((x&0xFF00)<<8) | ((x&0xFF0000)>>8) | (x>>24) )
  36.  
  37. struct Library *SocketBase=NULL;
  38. u_long nap_sigmask;
  39. long nap_sock= -1;
  40. long loc_sock= -1;
  41.  
  42. char nap_host[512];
  43. char nap_server[512+6];
  44.  
  45. int nap_state= -1;
  46. #define NAPS_OFF -1
  47. #define NAPS_MAINCON 0
  48. #define NAPS_MAINON 1
  49. #define NAPS_CON 2
  50. #define NAPS_ON 3
  51.  
  52. char nap_buffer[AMSTER_NAPBUFSIZE];
  53. char *nap_buf = &nap_buffer[4];
  54.  
  55. char *nap_linktype[] = {
  56.     (char*)_MSG_LINE_UNKNOWN,
  57.     (char*)_MSG_LINE_14400,
  58.     (char*)_MSG_LINE_28800,
  59.     (char*)_MSG_LINE_33600,
  60.     (char*)_MSG_LINE_57600,
  61.     (char*)_MSG_LINE_64000,
  62.     (char*)_MSG_LINE_128000,
  63.     (char*)_MSG_LINE_CABLE,
  64.     (char*)_MSG_LINE_DSL,
  65.     (char*)_MSG_LINE_T1,
  66.     (char*)_MSG_LINE_T3,
  67.     NULL
  68. };
  69.  
  70. BOOL nap_logininit(void);
  71. int nap_connect(char *server);
  72. int nap_recv(u_char *buf);
  73. void nap_interpret(u_int com, char *data);
  74. void nap_parseresult(int type, char *data);
  75. char *nap_token(char **s);
  76. u_long nap_ltoken(char **str);
  77. int nap_itoken(char **str);
  78. int createlistener(void);
  79. char *getneterror(int type);
  80.  
  81.  
  82. void nap_login_fromlist(char *server)
  83. {
  84.     if (!nap_logininit()) return;
  85.  
  86.     nap_state = NAPS_CON;
  87.     gui_stat((char*)MSG_STATUS2_CONNECTINGTO, server);
  88.     if (!nap_connect(server)) {
  89.         nap_logout();
  90.         return;
  91.     }
  92. }
  93.  
  94.  
  95. void nap_login(void)
  96. {
  97.     if (!nap_logininit()) return;
  98.  
  99.     if (prf->server) {
  100.         nap_state = NAPS_CON;
  101.         gui_stat((char*)MSG_STATUS2_CONNECTINGTO, prf->server);
  102.         if (!nap_connect(prf->server)) {
  103.             nap_logout();
  104.             return;
  105.         }
  106.     }
  107.     else {
  108.         nap_state = NAPS_MAINCON;
  109.         gui_stat((char*)MSG_STATUS2_FINDINGOPTIMAL);
  110.         if (!nap_connect(prf->mainserver)) {
  111.             nap_logout();
  112.             return;
  113.         }
  114.     }
  115. }
  116.  
  117.  
  118. BOOL nap_logininit(void)
  119. {
  120.     gui_state(0);
  121.     SocketBase = OpenLibrary("bsdsocket.library", 0);
  122.     if (!SocketBase) {
  123.         gui_stat((char *)MSG_NO_TCPIP);
  124.         nap_logout();
  125.         return FALSE;
  126.     }
  127.     SocketBaseTags(SBTM_SETVAL(SBTC_SIGIOMASK), (char *)nap_sigmask, TAG_DONE);
  128.  
  129.     return TRUE;
  130. }
  131.  
  132.  
  133. void nap_logout(void)
  134. {
  135.     nap_state = NAPS_OFF;
  136.     if (nap_sock>=0) CloseSocket(nap_sock);
  137.     nap_sock = -1;
  138.     if (loc_sock>=0) CloseSocket(loc_sock);
  139.     loc_sock = -1;
  140.     if (SocketBase) CloseLibrary(SocketBase);
  141.     SocketBase = NULL;
  142.     gui_state(-1);
  143. }
  144.  
  145.  
  146. void nap_listen(void)
  147. {
  148.     static u_char buf[AMSTER_NAPBUFSIZE];
  149.     static struct fd_set fds;
  150.     static struct timeval tv;
  151.  
  152.     if (nap_state == NAPS_OFF) return;
  153.  
  154.     FD_ZERO(&fds);
  155.     FD_SET(nap_sock,&fds);
  156.     tv.tv_sec = 0;
  157.     tv.tv_usec = 0;
  158.  
  159.     switch (nap_state) {
  160.         case NAPS_MAINCON:
  161.             if (WaitSelect(nap_sock+1,NULL,&fds,NULL,&tv,0) != 1) break;
  162.             {
  163.                 long tmp=0;
  164.                 IoctlSocket(nap_sock,FIONBIO,(char*)&tmp);
  165.                 nap_state = NAPS_MAINON;
  166.             }
  167.  
  168.         case NAPS_MAINON:
  169.             if (WaitSelect(nap_sock+1,&fds,NULL,NULL,&tv,0) != 1) break;
  170.             {
  171.                 int r;
  172.                 char *col;
  173.                 r = recv(nap_sock, buf, 255,0);
  174.                 CloseSocket(nap_sock);
  175.                 nap_sock = -1;
  176.                 if (r <= 0) {
  177.                     gui_stat((char *)MSG_STATUS2_CONNECTFAILED_TMP, nap_server, getneterror(Errno()));
  178.                     nap_logout();
  179.                     return;
  180.                 }
  181.                 buf[r] = 0;
  182.                 col = strchr(buf, '\n');
  183.                 if (col) *col=0;
  184.                 if (strncmp(buf,"wait",4)==0 || strncmp(buf,"busy",4)==0 || strncmp(buf,"127.0.0.1",9)==0) {
  185.                     /* Sometimes the server returns "127.0.0.1:1111" - quite odd. */
  186.                     gui_stat((char *)MSG_INFO_SERVERBUSY);
  187.                     nap_logout();
  188.                     return;
  189.                 }
  190.                 gui_debugf((char *)MSG_INFO_OPTIMAL, buf);
  191.                 gui_stat((char *)MSG_STATUS2_CONNECTINGTO, buf);
  192.                 if (!nap_connect(buf)) {
  193.                     nap_logout();
  194.                     return;
  195.                 }
  196.                 nap_state = NAPS_CON;
  197.             }
  198.             break;
  199.  
  200.         case NAPS_CON:
  201.             if (WaitSelect(nap_sock+1,NULL,&fds,NULL,&tv,0) != 1) break;
  202.             {
  203.                 long tmp=0;
  204.                 int r = 0;
  205.  
  206.                 IoctlSocket(nap_sock, FIONBIO, (char *)&tmp);
  207.  
  208.                 nap_state = NAPS_ON;
  209.                 gui_stat((char *)MSG_STATUS2_LOGGINGINTO, nap_server);
  210.                 gui_state(1);
  211.  
  212.                 DoMethod(gui->WI_Navigator, NAVI_MARKSERVER, nap_server);
  213.  
  214.                 if (prf->regflag > 0) {
  215.                     r = nap_sendbuf(NAPC_CHECK_NAME, prf->user);
  216.                     /* Create user before we attempt to log in */
  217.  
  218.                     if (r == -1) {
  219.                         prf->regflag = 1;
  220.                         if (Errno() == EPIPE) {
  221.                             gui_stat((char *)MSG_STATUS2_CONNECTFAILED_TMP, nap_server, getneterror(Errno()));
  222.                             nap_logout();
  223.                             return;
  224.                         }
  225.                     }
  226.                 }
  227.  
  228.                 if (prf->regflag == 1) {
  229.                     sprintf(nap_buf, "%s %s %d \"%s\" %d", prf->user, prf->pass, 0/*prf->port*/, prf->napvers, prf->link);
  230.                 }
  231.                 else {
  232.                     sprintf(nap_buf, "%s %s %d \"%s\" %d", gui->ConnectUser, gui->ConnectPw, 0/*prf->port*/, prf->napvers, prf->link);
  233.                 }
  234.                 prf->regflag = 1;
  235.                 nap_send(NAPC_LOGIN_REQUEST);
  236.             }
  237.             break;
  238.  
  239.         case NAPS_ON:
  240.             while (1) {
  241.                 int r;
  242.                 FD_ZERO(&fds);
  243.                 FD_SET(nap_sock,&fds);
  244.                 tv.tv_sec=0;
  245.                 tv.tv_usec=0;
  246.                 if (WaitSelect(nap_sock+1, &fds, NULL, NULL, &tv, 0) < 1) {
  247.                     return;
  248.                 }
  249.  
  250.                 r = nap_recv(buf);
  251.                 if (r == -1) {
  252.                     gui_stat((char *)MSG_ERR_NETWORKERROR);
  253.                     nap_logout();
  254.                     return;
  255.                 }
  256.                 if (r == 1) nap_interpret(buf[2]+(buf[3]<<8), buf+4);
  257.             }
  258.     }
  259. }
  260.  
  261.  
  262. void nap_send(u_int com)
  263. {
  264.     int len;
  265.  
  266.     if (!gui_napon) return;
  267.     /* Avoid crash - but calling functions should check this first! */
  268.  
  269.     len = strlen(nap_buf);
  270.     nap_buffer[0] = len&0xFF;
  271.     nap_buffer[1] = (len&0xFF00)>>8;
  272.     nap_buffer[2] = com&0xFF;
  273.     nap_buffer[3] = (com&0xFF00)>>8;
  274.     send(nap_sock,nap_buffer,4+len,0);
  275. }
  276.  
  277.  
  278. int nap_sendbuf(u_int com, char *buf)
  279. {
  280.     static u_char hdr[4];
  281.     int len, r;
  282.  
  283.     if (!gui_napon) return -1;
  284.     /* Avoid crash - but calling functions should check this first! */
  285.  
  286.     len = strlen(buf);
  287.     hdr[0] = len&0xFF;
  288.     hdr[1] = (len&0xFF00)>>8;
  289.     hdr[2] = com&0xFF;
  290.     hdr[3] = (com&0xFF00)>>8;
  291.  
  292.     r = send(nap_sock, hdr, 4, 0);
  293.     if (r <= 0) return r;
  294.  
  295.     r = send(nap_sock, buf, len, 0);
  296.     if (r <= 0) return r;
  297.     else return 0;
  298. }
  299.  
  300.  
  301. void nap_songfree(song s)
  302. {
  303.     if (!s) return;
  304.     if (s->title) free(s->title);
  305.     if (s->md5) free(s->md5);
  306.     if (s->user) free(s->user);
  307.     free(s);
  308. }
  309.  
  310.  
  311. song nap_songdup(song s)
  312. {
  313.     song sn;
  314.  
  315.     sn = malloc(sizeof(_song));
  316.     if (!sn) return(NULL);
  317.     memset(sn,0,sizeof(_song));
  318.  
  319.     sn->title = strdup(s->title);
  320.     sn->md5 = strdup(s->md5);
  321.     sn->size = s->size;
  322.     sn->bit = s->bit;
  323.     sn->freq = s->freq;
  324.     sn->time = s->time;
  325.     sn->user = strdup(s->user);
  326.     sn->ip = s->ip;
  327.     sn->link = s->link;
  328.  
  329.     if (!sn->title || !sn->md5 || !sn->user) {
  330.         nap_songfree(sn);
  331.         return(NULL);
  332.     }
  333.  
  334.     return(sn);
  335. }
  336.  
  337.  
  338. char *nap_strippath(char *name)
  339. {
  340.     int i;
  341.     char tmp;
  342.  
  343.     for (i=strlen(name)-1; i>=0; i--) {
  344.         tmp = name[i];
  345.         if (tmp==':' || tmp=='/' || tmp=='\\') return(name+i+1);
  346.     }
  347.     return(name);
  348. }
  349.  
  350.  
  351. /* private functions */
  352.  
  353. int nap_connect(char *server)
  354. {
  355.     struct hostent *host;
  356.     struct sockaddr_in sin;
  357.     long tmp=1;
  358.     char *addr, *col;
  359.     int port = 0;
  360.  
  361.     addr = strdup(server);
  362.     col = strtok(addr, ":");
  363.     if (col) col = strtok(NULL,"");
  364.     if (col) port = atoi(col);
  365.  
  366.     if (!port) {
  367.         gui_stat((char *)MSG_INFO_PORTNEEDED);
  368.         free(addr);
  369.         return(0);
  370.     }
  371.  
  372.     host = gethostbyname(addr);
  373.     free(addr);
  374.     if (!host) {
  375.         gui_stat((char *)MSG_ERR_LOOKUPFAILED);
  376.         return(0);
  377.     }
  378.     memcpy(&sin.sin_addr, host->h_addr, host->h_length);
  379.     sin.sin_family = host->h_addrtype;
  380.     sin.sin_port = port;
  381.     sin.sin_len = sizeof(sin);
  382.  
  383.     strcpy(nap_host, host->h_name);
  384.     strcpy(nap_server, server);
  385.  
  386.     nap_sock = socket(AF_INET,SOCK_STREAM,0);
  387.     if (nap_sock<0) {
  388.         gui_debug((char *)MSG_ERR_SOCKETERROR);
  389.         return(0);
  390.     }
  391.  
  392.     IoctlSocket(nap_sock,FIOASYNC,(char *)&tmp);
  393.     IoctlSocket(nap_sock,FIONBIO,(char *)&tmp);
  394.  
  395.     tmp = connect(nap_sock, (struct sockaddr *)&sin, sizeof(struct sockaddr_in));
  396.     if(tmp != -1) return(1);
  397.     if(Errno()==EINPROGRESS) return(1);
  398.  
  399.     gui_stat((char *)MSG_STATUS2_CONNECTFAILED_TMP, nap_host, getneterror(Errno()));
  400.     return(0);
  401. }
  402.  
  403.  
  404. int nap_recv(u_char *buf)
  405. {
  406.     static u_int blen=0;
  407.     u_int len=4;
  408.     int ret;
  409.  
  410.     if (blen>=4) {
  411.         len = buf[0] + (buf[1]<<8) + 4;
  412.         if (len==0) {
  413.             buf[blen] = 0;
  414.             blen = 0;
  415.             return(1);
  416.         }
  417.     }
  418.  
  419.  
  420.     ret = recv(nap_sock, buf+blen, len-blen, 0);
  421.     if (ret <= 0) {
  422.         blen = 0;
  423.         return(-1);
  424.     }
  425.     blen += ret;
  426.  
  427.  
  428.     if (blen == 4) {
  429.         len = buf[0] + (buf[1]<<8) + 4;
  430.         if (len == 0) {
  431.             buf[blen] = 0;
  432.             blen = 0;
  433.             return(1);
  434.         }
  435.     }
  436.  
  437.     if (blen == len) {
  438.         buf[blen] = 0;
  439.         blen = 0;
  440.         return(1);
  441.     }
  442.  
  443.     return(0);
  444. }
  445.  
  446.  
  447. void nap_interpret(u_int com, char *data)
  448. {
  449.     switch(com) {
  450.         case NAPC_PUBLICMSGRECV:
  451.         case NAPC_JOINACK:
  452.         case NAPC_JOINMSG:
  453.         case NAPC_USERPART:
  454.         case NAPC_USERLIST:
  455.         case NAPC_USERLISTEND:
  456.         case NAPC_CHANNELTOPIC:
  457.             chat_interpret(com, data);
  458.             break;
  459.         case NAPC_CHANNELPART:
  460.             gui_debugf("Left channel %s.", data);
  461.             break;
  462.         case NAPC_CHANNEL_ENTRY:
  463.             {
  464.             char *channel;
  465.             int users;
  466.  
  467.             channel = nap_token(&data);
  468.             users = nap_itoken(&data);
  469.             DoMethod(gui->WI_ChannelList, CHANLIST_ENTRY, channel, users, data);
  470.             break;
  471.             }
  472.         case NAPC_LIST_CHANNELS:
  473.             /* End of channel list */
  474.             break;
  475.         case NAPC_USER_SIGNON:
  476.         case NAPC_USER_SIGNOFF:
  477.         case NAPC_HOTLIST_ACK:
  478.         case NAPC_HOTLIST_ERROR:
  479.             HotlistInterpret(com, data);
  480.             break;
  481.         case NAPC_LOGINERROR:
  482.             gui_debugf((char *)MSG_INFO_LOGINERROR, data);
  483.             break;
  484.         case NAPC_REGSUCCESS:
  485.             gui_debug((char *)MSG_INFO_REGSUCCESS);
  486.             break;
  487.         case NAPC_REGUSED:
  488.             gui_debug((char *)MSG_INFO_REGUSED);
  489.             break;
  490.         case NAPC_SEARCHRESULT:
  491.             nap_parseresult(0, data);
  492.             break;
  493.         case NAPC_SEARCHCOMPLETE:
  494.             gui_found(NULL, 0);
  495.             break;
  496.         case NAPC_BROWSERESULT:
  497.             nap_parseresult(1, data);
  498.             break;
  499.         case NAPC_BROWSECOMPLETE:
  500.             gui_found(NULL, 1);
  501.             break;
  502.         case NAPC_FILECOUNT:
  503.             {
  504.             int a,b,c;
  505.             a = nap_itoken(&data);
  506.             b = nap_itoken(&data);
  507.             c = nap_itoken(&data);
  508.             gui_srvstat(a,b,c);
  509.             break;
  510.             }
  511.         case NAPC_PRIVATEMSG:
  512.             {
  513.             char *nick;
  514.  
  515.             nick = nap_token(&data);
  516.             DoMethod(gui->mwin, MSG_GOT, nick, data);
  517.             break;
  518.             }
  519.         case NAPC_FILEINFO:
  520.             {
  521.             char *title,*user;
  522.             u_long ip;
  523.             int port;
  524.  
  525.             user = nap_token(&data);
  526.             ip = nap_ltoken(&data);
  527.             port = nap_itoken(&data);
  528.             title = nap_token(&data);
  529.  
  530.             DoMethod(gui->dwin, DL_START, title, user, NAP_SWAPIP(ip), port);
  531.             }
  532.             break;
  533.         case NAPC_LOGINRESP:
  534.             DoMethod(gui->WI_Hotlist, HOTLIST_UPLOAD);
  535.             DoMethod(gui->shwin, SHARE_NOTIFYALL);
  536.             gui_state(2);
  537.             break;
  538.         case NAPC_WHOISRESP:
  539.             msg_gotwhois(data);
  540.             break;
  541.         case NAPC_WHOWASRESP:
  542.             {
  543.             char *user, *level;
  544.             u_long lastseen;
  545.  
  546.             user = nap_token(&data);
  547.             level = nap_token(&data);
  548.             lastseen = nap_ltoken(&data);
  549.  
  550.             DoMethod(gui->mwin, MSG_WHOWAS, user, level, lastseen);
  551.             }
  552.             break;
  553.         case NAPC_UPLOADREQ:
  554.             {
  555.             char *user,*fname;
  556.             user = nap_token(&data);
  557.             fname = nap_token(&data);
  558.             upload_req(user,fname);
  559.             }
  560.             break;
  561.         case NAPC_ALTDLACK:
  562.             {
  563.             char *nick, *fname, *md5;
  564.             u_long ip;
  565.             int port, speed;
  566.  
  567.             nick = nap_token(&data);
  568.             ip = nap_ltoken(&data);
  569.             port = nap_itoken(&data);
  570.             fname = nap_token(&data);
  571.             md5 = nap_token(&data);
  572.             speed = nap_itoken(&data);
  573.  
  574.             ul_startq(fname, nick, NAP_SWAPIP(ip), port, speed);
  575.             }
  576.             break;
  577.         case NAPC_REMOTEQUEUEFULL:
  578.             {
  579.             char *nick, *fname;
  580.             int size, limit;
  581.             nick = nap_token(&data);
  582.             fname = nap_token(&data);
  583.             size = nap_itoken(&data);
  584.             limit = nap_itoken(&data);
  585.  
  586.             DoMethod(gui->dwin, DL_RETRY, fname, nick, limit);
  587.             }
  588.             break;
  589.         case NAPC_GETERROR:
  590.         case NAPC_GETERROR2:
  591.             {
  592.             char *user, *fname;
  593.             user = nap_token(&data);
  594.             fname = nap_token(&data);
  595.             DoMethod(gui->dwin, DL_SETERROR, fname, user, ERROR_LOGGEDOUT);
  596.             }
  597.             break;
  598.         case NAPC_GENERALERROR:
  599.             gui_debugf((char *)MSG_INFO_ERROR, data);
  600.             break;
  601.         case NAPC_SYSMSG:
  602.             gui_debug(data);
  603.             break;
  604.         case NAPC_GLOBALMSG:
  605.             {
  606.             char *nick, buf[50];
  607.  
  608.             nick = nap_token(&data);
  609.             sprintf(buf, MSG_GLOBALMESSAGE_TITLE, nick);
  610.  
  611.             MUI_Request(gui->app, gui->win, 0L,
  612.                 buf,
  613.                 (char *)MSG_OK_GAD,
  614.                 data);
  615.             }
  616.             break;
  617.         default:
  618.             gui_debugf("<<%d:%s>>",com,data);
  619.     }
  620. }
  621.  
  622.  
  623. void nap_parseresult(int type, char *data)
  624. {
  625.     song s;
  626.     char *tmp=data;
  627.  
  628.     s = malloc(sizeof(_song));
  629.     if(!s) return;
  630.     memset(s,0,sizeof(_song));
  631.  
  632.     switch (type) {
  633.         case 0:    /* Search result */
  634.             s->title = strdup(nap_token(&tmp));
  635.             s->md5 = strdup(nap_token(&tmp));
  636.             strtok(s->md5,"-");
  637.             s->size = nap_ltoken(&tmp);
  638.             s->bit = nap_itoken(&tmp);
  639.             s->freq = nap_itoken(&tmp);
  640.             s->time = nap_itoken(&tmp);
  641.             s->user = strdup(nap_token(&tmp));
  642.             s->ip = nap_ltoken(&tmp);
  643.             s->ip = NAP_SWAPIP(s->ip);
  644.             s->link = nap_itoken(&tmp);
  645.             break;
  646.  
  647.         case 1: /* Browse result */
  648.             s->user = strdup(nap_token(&tmp));
  649.             s->title = strdup(nap_token(&tmp));
  650.             s->md5 = strdup(nap_token(&tmp));
  651.             strtok(s->md5, "-");
  652.             s->size = nap_ltoken(&tmp);
  653.             s->bit = nap_itoken(&tmp);
  654.             s->freq = nap_itoken(&tmp);
  655.             s->time = nap_itoken(&tmp);
  656.             break;
  657.     }
  658.  
  659.     if (!s->user || !s->title || !s->md5) {
  660.         nap_songfree(s);
  661.         return;
  662.     }
  663.  
  664.     gui_found(s, type);
  665. }
  666.  
  667.  
  668. u_long nap_ltoken(char **str)
  669. {
  670.     char *t;
  671.  
  672.     t = nap_token(str);
  673.     if(!t) return(0);
  674.     return((u_long)atol(t));
  675. }
  676.  
  677.  
  678. int nap_itoken(char **str)
  679. {
  680.     char *t;
  681.  
  682.     t = nap_token(str);
  683.     if(!t) return(0);
  684.     return(atoi(t));
  685. }
  686.  
  687.  
  688. char *nap_token(char **str)
  689. {
  690.     int sf=0,i,len=0;
  691.     char c, *t=NULL;
  692.  
  693.     if (!*str) return(NULL);
  694.  
  695.     for (i=0; ; i++) {
  696.         c = *(*str + i);
  697.         switch (c) {
  698.             case '\0':
  699.                 *str = NULL;
  700.                 if (len==0 || sf) return(NULL);
  701.                 return(t);
  702.             case '"':
  703.                 if (sf) {
  704.                     *(*str+i) = 0;
  705.                     *str = *str+i+1;
  706.                     return(t);
  707.                 }
  708.                 sf=1;
  709.                 break;
  710.             case ' ':
  711.                 if (len==0) break;
  712.                 if (!sf) {
  713.                     *(*str+i) = 0;
  714.                     *str = *str+i+1;
  715.                     return(t);
  716.                 }
  717.                 break;
  718.             default:
  719.                 if (!t) t=*str+i;
  720.                 len++;
  721.         }
  722.     }
  723. }
  724.  
  725.  
  726. /*
  727. int createlistener(void)
  728. {
  729.     struct sockaddr_in server;
  730.  
  731.     if (loc_sock != -1) return 1;
  732.  
  733.     loc_sock = socket(AF_INET, SOCK_STREAM, 0);
  734.     if (loc_sock < 0) {
  735.         gui_debug("Error creating listener socket!\n");
  736.         return 0;
  737.     }
  738.  
  739.     server.sin_family = AF_INET;
  740.     server.sin_addr.s_addr = htonl(INADDR_ANY);
  741.     server.sin_port = htons(prf->port);
  742.  
  743.     if (bind(loc_sock, (struct sockaddr *)&server, sizeof(server)) < 0) {
  744.         gui_debug("Error binding listening socket\n");
  745.         CloseSocket(loc_sock);
  746.         loc_sock = -1;
  747.         return 0;
  748.     }
  749.  
  750.     listen(loc_sock, 0);    / Number of allowed connections /
  751.  
  752.     return 1;
  753. }
  754. */
  755.  
  756.  
  757. char *getneterror(int type)
  758. {
  759.     char *message, buf[512];
  760.  
  761.     switch (type) {
  762.         case ENETDOWN:
  763.             message = (char *)MSG_NETERROR_ENETDOWN;
  764.             break;
  765.         case ENETUNREACH:
  766.             message = (char *)MSG_NETERROR_ENETUNREACH;
  767.             break;
  768.         case ECONNRESET:
  769.             message = (char *)MSG_NETERROR_ECONNRESET;
  770.             break;
  771.         case ETIMEDOUT:
  772.             message = (char *)MSG_NETERROR_ETIMEDOUT;
  773.             break;
  774.         case ECONNREFUSED:
  775.             message = (char *)MSG_NETERROR_ECONNREFUSED;
  776.             break;
  777.         case EPIPE:
  778.             message = (char *)MSG_NETERROR_EPIPE;
  779.             break;
  780.         default:
  781.             sprintf(buf, MSG_NETERROR_UNKNOWN, type);
  782.             message = buf;
  783.     }
  784.  
  785.     return message;
  786. }
  787.